class Canvas {
  constructor(id, width, height) {
    this.dpr = window.devicePixelRatio || 1;
    this.canvas = document.getElementById("" + id);
    this.canvas.width = width;
    this.canvas.height = height;

    this.ctx = this.canvas.getContext("2d");
    this.drawNum = 0;

    this.clickX = 0;
    this.clickY = 0;

    this.lineSpot = [];
  }
  drawTxt(params = { value, x, y, size, color, fw: "normal", deg }) {
    this.ctx.save();
    let defaultParams = {
      value: "",
      x: 0,
      y: 0,
      size: 12,
      color: "#000",
      fw: "normal",
      fm: "Arial",
      deg: 0,
      fs: "normal",
    };
    let options = { ...defaultParams, ...params };
    this.ctx.fillStyle = options.color || "#000";
    this.ctx.font =
      options.fs + " normal " + options.fw + " " + options.size + "px Arial";
    let valWidht = this.ctx.measureText(options.value).width;

    let translateX = 0;
    let translateY = 0;
    if (options.deg > 0) {
      translateX =
        options.x +
        this.keepTwoDecimal(valWidht / 2) *
          (1 - Math.cos((options.deg * Math.PI * 2) / 360));
      translateY =
        options.y -
        this.keepTwoDecimal(valWidht / 2) *
          Math.sin((options.deg * Math.PI * 2) / 360);

      this.ctx.translate(
        this.keepTwoDecimal(translateX),
        this.keepTwoDecimal(translateY)
      );

      this.ctx.rotate((options.deg * Math.PI) / 180);
      this.ctx.fillText(options.value, 0, 0);
      this.ctx.restore();
    } else {
      this.ctx.fillText(options.value, options.x, options.y);
    }
  }
  drawImg(params = { url, x, y, w, h, deg: 0 }) {
    this.ctx.save();
    let defaultParams = {
      url: "",
      x: 0,
      y: 0,
      w: this.canvas.width,
      h: this.canvas.height,
      deg: 0,
    };
    let options = { ...defaultParams, ...params };
    let _this = this;
    return new Promise((resolve, reject) => {
      const imgUpload = new Image();
      imgUpload.setAttribute("crossOrigin", "Anonymous");
      imgUpload.src = options.url;
      imgUpload.onload = () => {
        let translateX = 0;
        let translateY = 0;
        if (options.deg > 0) {
          translateX = options.x + options.w / 2;
          translateY = options.y + options.h / 2;

          _this.ctx.translate(
            _this.keepTwoDecimal(translateX),
            _this.keepTwoDecimal(translateY)
          );

          _this.ctx.rotate((options.deg * Math.PI) / 180);
          _this.ctx.translate(
            _this.keepTwoDecimal(-1 * translateX),
            _this.keepTwoDecimal(-1 * translateY)
          );
        }
        _this.ctx.drawImage(
          imgUpload,
          options.x,
          options.y,
          options.w,
          options.h
        );
        _this.ctx.restore();
        _this.drawNum += 1;
        resolve();
      };
    });
  }

  // 判断点是否在直线上
  isInLine(params = { x1, y1, x2, y2, tx, ty }) {
    let { x1, y1, x2, y2, tx, ty } = params;
    let k = -1 * x1 + y1;
    let k2 = -1 * tx + ty;
    if (k == k2) {
      return true;
    }
    return false;
  }

  // 根据点击位置绘制线条
  clickLine(
    params = {
      lineColor: "#000",
      showTxt: false,
      size: 12,
      color: "#000",
    }
  ) {
    this.ctx.save();
    let length = this.lineSpot.length;
    if (length <= 1) {
      if (length == 1) {
        if (params.showTxt) {
          this.drawTxt({
            value: this.lineSpot.length,
            x: this.lineSpot[length - 1].x,
            y: this.lineSpot[length - 1].y,
            size: params.size,
            color: params.color,
          });
        }
      }
      return;
    }
    this.ctx.strokeStyle = "" + params.lineColor;
    this.ctx.beginPath();
    this.ctx.moveTo(this.lineSpot[length - 2].x, this.lineSpot[length - 2].y);
    this.ctx.lineTo(this.lineSpot[length - 1].x, this.lineSpot[length - 1].y);
    this.ctx.closePath();
    this.ctx.stroke();
    if (params.showTxt) {
      this.drawTxt({
        value: this.lineSpot.length,
        x: this.lineSpot[length - 1].x,
        y: this.lineSpot[length - 1].y,
        size: params.size,
        color: params.color,
      });
    }
    this.ctx.restore();
  }

  // 监听点击
  onClick(
    params = {
      drawLine: false,
      lineParams: {
        lineColor: "#000",
        showTxt: false,
        size: 12,
        color: "#000",
      },
    }
  ) {
    this.canvas.onclick = (event) => {
      this.getMousePos(event);
      if (params.drawLine) {
        this.clickLine(params.lineParams);
      }
    };
  }

  // 获取点击的坐标数据
  getClickSpot() {
    return { x: this.clickX, y: this.clickY };
  }
  // 移除监听点击
  removeClick() {
    this.canvas.onclick = () => {
      this.lineSpot = [];
      return false;
    };
  }
  // 保留两位小数
  keepTwoDecimal(num) {
    let result = parseFloat(num);
    if (isNaN(result)) {
      alert("传递参数错误，请检查！");
      return false;
    }
    result = Math.round(num * 100) / 100;
    return result;
  }

  // 获取鼠标位置
  getMousePos(event) {
    let rect = this.canvas.getBoundingClientRect();
    this.clickX = event.clientX - rect.left * (this.canvas.width / rect.width);
    this.clickY = event.clientY - rect.top * (this.canvas.height / rect.height);
    this.lineSpot.push({
      x: this.clickX,
      y: this.clickY,
    });
  }
}

const JsCanvas = {
  newCanvas: null,
  init: (id = "canvas", w = 300, h = 300) => {
    JsCanvas.newCanvas = new Canvas(id, w, h);
  },
  text: (params = { value, x, y, size, color, fw: "normal", deg }) => {
    JsCanvas.newCanvas.drawTxt(params);
  },
  img: (params = { url, x, y, w, h, deg: 0 }) => {
    JsCanvas.newCanvas.drawImg(params);
  },
  inLine: (
    params = {
      x1,
      y1,
      x2,
      y2,
      tx,
      ty,
    }
  ) => {
    return JsCanvas.newCanvas.isInLine({ ...params });
  },
  clickLine: (
    params = {
      lineColor: "#000",
      showTxt: true,
      size: 12,
      color: "#000",
    }
  ) => {
    let defaultParams = {
      lineColor: "#000",
      showTxt: true,
      size: 12,
      color: "#000",
    };
    JsCanvas.newCanvas.onClick({
      drawLine: true,
      lineParams: { ...defaultParams, ...params },
    });
  },
  unClick: () => {
    JsCanvas.newCanvas.removeClick();
  },
};
module.exports = JsCanvas;
